;;; org-settings.el --- Configure org in zuojg's Emacs
;; -*- Emacs-Lisp -*-

;; Time-stamp: <2010-04-12 23:54:20 Monday by Mugua>

;; This  file is free  software; you  can redistribute  it and/or
;; modify it under the terms of the GNU General Public License as
;; published by  the Free Software Foundation;  either version 3,
;; or (at your option) any later version.

;; This file is  distributed in the hope that  it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR  A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You  should have  received a  copy of  the GNU  General Public
;; License along with  GNU Emacs; see the file  COPYING.  If not,
;; write  to  the Free  Software  Foundation,  Inc., 51  Franklin
;; Street, Fifth Floor, Boston, MA 02110-1301, USA.


;;; Commentary:
;;
;; Edit by zuojg

;;; Code:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; 设置org-mode
;;; Edit by zuojg
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;       --------------------------
;;       |        Jianguang ZUO   |
;;       |             zuojg@msn  |
;;       |    Org-mode            |
;;       |  My life in Plain text |
;;       --------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(add-to-list 'load-path  (concat my-emacs-path "Org"))
(require 'org)
(add-to-list 'auto-mode-alist '("\\.org$" . org-mode))
(define-key global-map "\C-cl" 'org-store-link)
(define-key global-map "\C-ca" 'org-agenda)
(global-set-key "\C-cb" 'org-iswitchb)
;;只高亮显示最后一个代表层级的
(setq org-hide-leading-stars t)
;;给已完成事项打上时间戳。可选 note，附加注释
(setq org-log-done 'time)
(setq org-log-done t)
;;设置自动装载的org 文件
(setq org-agenda-files (list (concat my-emacs-path "Org/budget.org")
                             (concat my-emacs-path "Org/graduate.org")
                             (concat my-emacs-path "Org/home.org")
                             (concat my-emacs-path "Org/improve.org")
                             (concat my-emacs-path "Org/note.org")
                             (concat my-emacs-path "Org/paper.org")
                             (concat my-emacs-path "Org/refile.org")
                                                            ))
; 设置diary 文件
(setq diary-file (concat my-emacs-path "Diary/diary"))
(setq diary-mail-addr "zuojg@126.com")
(add-hook 'diary-hook 'appt-make-list)
; org-mode 自动填充
(defun general-org-mode-fill-hook ()
  (interactive)
  (setq normal-auto-fill-function
        (lambda ()
          (interactive)
          (do-auto-fill)))
  (setq fill-column 72)
  (auto-fill-mode))
(add-hook 'org-mode-hook 'general-org-mode-fill-hook)
;;把org模式设置为org,org_archive和txt文件类型的默认模式
(add-to-list 'auto-mode-alist '("\\.\\(org\\|org_archive\\|txt\\)$" . org-mode))
(require 'org-install)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 杭州的经度维度，以便在calendar 中显示日出日落时间
;; 快捷键 S
(setq calendar-latitude 30.3)
(setq calendar-longitude 120.2)
(setq calendar-location-name "杭州")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 设置阴历显示，在 calendar 上用 pC 显示阴历
(setq chinese-calendar-celestial-stem
  ["甲" "乙" "丙" "丁" "戊" "己" "庚" "辛" "壬" "癸"])
(setq chinese-calendar-terrestrial-branch
  ["子" "丑" "寅" "卯" "辰" "巳" "戊" "未" "申" "酉" "戌" "亥"])
;; 设置 calendar 的显示
(setq calendar-remove-frame-by-deleting t)
(setq calendar-week-start-day 1)            ; 设置星期一为每周的第一天
(setq mark-diary-entries-in-calendar t)     ; 标记calendar上有diary的日期
(setq mark-holidays-in-calendar nil)        ; 为了突出有diary的日期，calendar上不标记节日
(setq view-calendar-holidays-initially nil) ; 打开calendar的时候不显示一堆节日
;; 去掉不关心的节日，设定自己在意的节日，在 calendar 上用 h 显示节日
(setq christian-holidays nil)
(setq hebrew-holidays nil)
(setq islamic-holidays nil)
(setq solar-holidays nil)
(setq general-holidays '((holiday-fixed 1 1 "元旦")
                         (holiday-fixed 2 14 "情人节")
                         (holiday-fixed 3 14 "白色情人节")
                         (holiday-fixed 4 1 "愚人节")
                         (holiday-fixed 5 1 "劳动节")
                         (holiday-float 5 0 2 "母亲节")
                         (holiday-fixed 6 1 "儿童节")
                         (holiday-float 6 0 3 "父亲节")
                         (holiday-fixed 7 1 "建党节")
                         (holiday-fixed 8 1 "建军节")
                         (holiday-fixed 9 10 "教师节")
                         (holiday-fixed 10 1 "国庆节")
                         (holiday-fixed 12 25 "圣诞节")))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;设置快捷键
(global-set-key (kbd "<f12>") 'org-agenda)
(global-set-key (kbd "<f5>") 'bh/org-todo)
(global-set-key (kbd "<S-f5>") 'widen)
(global-set-key (kbd "<f7>") 'set-truncate-lines)
(global-set-key (kbd "<f8>") 'org-cycle-agenda-files)
(global-set-key (kbd "<f9> b") 'bbdb)
(global-set-key (kbd "<f9> c") 'calendar)
(global-set-key (kbd "<f9> f") 'boxquote-insert-file)
(global-set-key (kbd "<f9> g") 'gnus)
(global-set-key (kbd "<f9> h") 'hide-other)
(global-set-key (kbd "<f9> i") (lambda ()
                                 (interactive)
                                 (info "~/git/org-mode/doc/org.info")))
(global-set-key (kbd "<f9> m") 'bh/clock-in-read-mail-and-news-task)
(global-set-key (kbd "<f9> o") 'bh/clock-in-organization-task)
(global-set-key (kbd "<f9> O") 'org-clock-out)
(global-set-key (kbd "<f9> r") 'boxquote-region)
(global-set-key (kbd "<f9> s") (lambda () (interactive) (switch-to-buffer "*scratch*") (delete-other-windows)))
(global-set-key (kbd "<f9> t") 'bh/insert-inactive-timestamp)
(global-set-key (kbd "<f9> u") (lambda ()
                                 (interactive)
                                 (untabify (point-min) (point-max))))
(global-set-key (kbd "<f9> v") 'visible-mode)
(global-set-key (kbd "<f9> SPC") 'bh/clock-in-interrupted-task)
(global-set-key (kbd "C-<f9>") 'previous-buffer)
(global-set-key (kbd "C-<f10>") 'next-buffer)
(global-set-key (kbd "<f11>") 'org-clock-goto)
(global-set-key (kbd "C-<f11>") 'org-clock-in)
(global-set-key (kbd "C-s-<f12>") 'bh/save-then-publish)
(global-set-key (kbd "M-<f11>") 'org-resolve-clocks)
(global-set-key (kbd "C-M-p") 'org-remember)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;TODO 状态关键词与颜色设置
(setq org-todo-keywords (quote ((sequence "TODO(t)" "STARTED(s!)" "|" "DONE(d!/!)")
 (sequence "WAITING(w@/!)" "SOMEDAY(S!)"  "|" "CANCELLED(c@/!)")
)))
(setq org-todo-keyword-faces (quote (("TODO" :foreground "red" :weight bold)
 ("STARTED" :foreground "blue" :weight bold)
 ("DONE" :foreground "forest green" :weight bold)
 ("WAITING" :foreground "orange" :weight bold)
 ("SOMEDAY" :foreground "magenta" :weight bold)
 ("CANCELLED" :foreground "forest green" :weight bold)
)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;TODO 状态触发
(setq org-todo-state-tags-triggers
      (quote (("CANCELLED" ("CANCELLED" . t))
              ("WAITING" ("WAITING" . t) ("NEXT"))
              ("SOMEDAY" ("WAITING" . t))
              (done ("NEXT") ("WAITING"))
              ("TODO" ("WAITING") ("CANCELLED") ("NEXT"))
              ("DONE" ("WAITING") ("CANCELLED") ("NEXT")))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;把Clocking 的任务自动设置为STARTED
(defun bh/clock-in-to-started (kw)
   "Switch task form TODO to STARTED when clocking in"
   (if (and (string-equal kw "TODO")
            (not (string-equal (buffer-name) "*Remember*")))
       "STARTED"
     nil))
(setq org-clock-in-switch-to-state (quote bh/clock-in-to-started))
;;快速TODO 状态变化选择
(setq org-use-fast-todo-selection t)
;;可用S-left 和S-right 来改变状态
(setq org-treat-S-cursor-todo-selection-as-state-change nil)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;设置日历自定义试图
(setq org-agenda-custom-commands
      (quote (("s" "Started Tasks" todo "STARTED" ((org-agenda-todo-ignore-scheduled nil)
                                                   (org-agenda-todo-ignore-deadlines nil)
                                                   (org-agenda-todo-ignore-with-date nil)))
              ("w" "Tasks waiting on something" tags "WAITING/!" ((org-use-tag-inheritance nil)))
              ("r" "Refile New Notes and Tasks" tags "LEVEL=1+REFILE" ((org-agenda-todo-ignore-with-date nil)
                                                                       (org-agenda-todo-ignore-deadlines nil)
                                                                       (org-agenda-todo-ignore-scheduled nil)))
              ("N" "Notes" tags "NOTE" nil)
              ("n" "Next" tags "NEXT-WAITING-CANCELLED/!" nil)
              ("p" "Projects" tags-todo "LEVEL=2-NEXT-WAITING-CANCELLED/!-DONE" nil)
              ("A" "Tasks to be Archived" tags "LEVEL=2/DONE|CANCELLED" nil)
              ("h" "Habits" tags "STYLE=\"habit\"" ((org-agenda-todo-ignore-with-date nil) (org-agenda-todo-ignore-scheduled nil) (org-agenda-todo-ignore-deadlines nil))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 日历视图属性调整
;;显示周期性任务的未来所有项
(setq org-agenda-repeating-timestamp-show-all t)
;;显示所有日期，即使是它是空的
(setq org-agenda-show-all-dates t)
;;以当天开始周视图
;(setq org-agenda-start-on-weekday nil)
;;不显示时间网格线
(setq org-agenda-time-grid
      (quote (nil "----------------"
                  (800 1000 1200 1400 1600 1800 2000))))
;;显示标签时更靠右点
(setq org-agenda-tags-column -102)
;;显示org 里的* 号
(setq org-hide-leading-stars nil)
;;处理空行
(setq org-cycle-separator-lines 0)
;; 禁止产生空行
(setq org-blank-before-new-entry (quote ((heading)(plain-list-item))))
;;笔记显示在顶部(主要是该项的一些说明，放在顶部在折叠时依旧可见）
(setq org-reverse-note-order nil)
;;在全局todo里面隐藏有确定日期的（截止期限和预定日期）任务，即隐藏有
;;DEADLINE 和SCHELED 的任务
(setq org-agenda-todo-ignore-with-date t)
;;从日历视图中移除已完成的有截止期限的任务
(setq org-agenda-skip-deadline-if-done t)
;;从日历视图中移除已完成的有预定日期的任务
(setq org-agenda-skip-scheduled-if-done t)
;;从查找结果中移除已完成的项
;(setq org-agenda-skip-timestamp-if-done t)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;以Remember 模式随时记录任务、笔记和电话
(defun bh/start-clock-if-needed ()
  (save-excursion
    (goto-char (point-min))
    (when (re-search-forward " *:CLOCK-IN: *" nil t)
      (replace-match "")
      (org-clock-in))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;设置Remember 模板
(setq org-default-notes-file (concat my-emacs-path "Org/refile.org"))
(require 'remember)
(org-remember-insinuate)
;;如果Remember 缓冲区里包含:CLOCK-IN: 的话启动时钟
(add-hook 'remember-mode-hook 'bh/start-clock-if-needed 'append)
;;使用快捷键C-M-r 来开始org-remember
(global-set-key (kbd "C-M-r") 'org-remember)
;;保持clock 运行
(setq org-remember-clock-out-on-exit nil)
;;使用快捷键C-c C-c 快速存储
(setq org-remember-store-without-prompt t)
;;万一在以后的模板里忘了制定位置时设定，一般不用
(setq org-remember-default-headline "Tasks")
;;3个 remember 模板分别为todo, note 和phone
(setq org-remember-templates (quote (("todo" ?t "* TODO %?\n  %u\n  %a" nil bottom nil)
                                     ("note" ?n "* %?                                        :NOTE:\n  %u\n  %a" nil bottom nil)
                                     ("phone" ?p "* PHONE %:name - %:company -                :PHONE:\n  Contact Info: %a\n  %u\n  :CLOCK-IN:\n  %?" nil bottom nil)
                                     ("appointment" ?a "* %?\n  %U" "D:/My dropbox/Emacs/Org/todo.org" "Appointments" nil)
                                     ("org-protocol" ?w "* TODO Review %c%!  :NEXT:\n  %U\n  :PROPERTIES:\n  :Effort: 0:10\n  :END:" nil bottom nil))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;把随时记录在Refiel.org 中的任务、笔记和电话移动到其他相应的org文件中去
;使用IDO 来实现目标自动完成
(setq org-completion-use-ido t)
; Targets include this file and any file contributing to the agenda - up to 5 levels deep
(setq org-refile-targets (quote ((org-agenda-files :maxlevel . 5) (nil :maxlevel . 5))))
; Targets start with the file name - allows creating level 1 tasks
(setq org-refile-use-outline-path (quote file))
; Targets complete in steps so we start with filename, TAB shows the next level of targets etc
(setq org-outline-path-complete-in-steps t)
; Allow refile to create parent tasks with confirmation
(setq org-refile-allow-creating-parent-nodes (quote confirm))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  设置Clocking
;;当emacs 重启时重设clocking 任务
(org-clock-persistence-insinuate)
;;长，但更好
(setq org-clock-history-length 28)
;;当clock 开放时重设clok-in 的cloking 任务
(setq org-clock-in-resume t)
;;当clocking in 的时自动把状态变为 STAETED
(setq org-clock-in-switch-to-state "STARTED")
;;把文件柜分为clocking 和log
(setq org-drawers (quote ("PROPERTIES" "LOGBOOK" "CLOCK")))
;;保存clock 数据在CLOCK 文件柜里，状态变化和LOGBOOK文件柜的笔记
(setq org-clock-into-drawer "CLOCK")
;;一按电钮更改任务是快速clocking，快速移除clocked 任务
(setq org-clock-out-remove-zero-time-clocks t)
;;当移动一个任务到完成状态时不Clock out
(setq org-clock-out-when-done nil)
;;退出时保存所有运行时钟和时钟历史，启动时装载进来
(setq org-clock-persist (quote history))
;;禁止自动时钟解决方案
(setq org-clock-auto-clock-resolution nil)
;;设定F9-m 为邮件任务设定时钟， F9-o 为任何缓冲区的组织任务设定缓冲区
;;f9-SPC 切换回到被打断的任务上去
(defun bh/clock-in-task-by-id (id)
  "Clock in a task by id"
  (require 'org-id)
  (save-restriction
    (widen)
    (org-with-point-at (org-id-find id 'marker)
      (org-clock-in nil))))
(defun bh/clock-in-organization-task ()
  (interactive)
  (bh/clock-in-task-by-id "437c2cde-fbf0-491f-92ba-51bae487b338"))
(defun bh/clock-in-read-mail-and-news-task ()
  (interactive)
  (bh/clock-in-task-by-id "85c2e69b-6f37-4236-8896-4f7dd86047c1"))
(defun bh/clock-in-interrupted-task ()
  "Clock in the interrupted task if there is one"
  (interactive)
  (if (and (not org-clock-resolving-clocks-due-to-idleness)
           (marker-buffer org-clock-marker)
           (marker-buffer org-clock-interrupted-task))
      (org-with-point-at org-clock-interrupted-task
        (org-clock-in nil))
    (org-clock-out)))
;;设定时间编辑为15钟的增量
(setq org-time-stamp-rounding-minutes (quote (1 15)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;设置时间报告和跟踪
;;由于我常常改变任务（甚至有时一分钟内都改变好几次），我使用下面的设定来迅速移除时钟项。
(setq org-clock-out-remove-zero-time-clocks t)
;;显示日历记录模式项（时钟时间只有默认）
(setq org-agenda-log-mode-items (quote (clock)))
;;日历时钟报告参数（无链接，2级深度）
(setq org-agenda-clockreport-parameter-plist (quote (:link nil :maxlevel 2)))
;;设置默认的列视图标题：任务时间统计
(setq org-columns-default-format "%80ITEM(Task) %10Effort(Effort){:} %10CLOCKSUM")
;;全局估计值
(setq org-global-properties (quote (("Effort_ALL" . "0:10 0:30 1:00 2:00 3:00 4:00 5:00 6:00 7:00 8:00"))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  设置tags
(setq org-tag-alist (quote ((:startgroup)
                            ("@实验室" . ?l)
                            ("@家里" . ?h)
                            ("@寝室" . ?b)
                            ("@路上" . ?r)
                            (:endgroup)
                            ("PHONE" . ?p)
                            ("COMPUTER" . ?p)
                            ("INTERNET" . ?i)
                            ("NEXT" . ?n)
                            ("WAITING" . ?w))))
;;允许无菜单设定单标签
(setq org-fast-tag-selection-single-key (quote expert))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; GTD Stuff
(setq org-agenda-ndays 1);;默认是显示当天的日视图
;;使项目向前运行
(setq org-stuck-projects (quote ("LEVEL=2-REFILE-WAITING|LEVEL=1+REFILE/!-DONE-CANCELLED-OPEN" nil ("NEXT") "")))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;  设置 存档
(setq org-archive-mark-done nil)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;一些可以提高工作效率的设置
;;一直高亮显示日历视图中的当前行
(add-hook 'org-agenda-mode-hook '(lambda () (hl-line-mode 1)))
;;查找时包括已存档的文件
(setq org-agenda-text-search-extra-files (quote (agenda-archives)))
;;隐藏空行
(setq org-cycle-separator-lines 0)
(setq org-blank-before-new-entry (quote ((heading)(plain-list-item))))
;;习惯养成跟踪（及其其他一些模块）
(setq org-modules (quote (org-bbdb org-bibtex org-crypt org-gnus org-id org-info org-jsinfo org-habit org-inlinetask org-irc org-mew org-mhe org-protocol org-rmail org-vm org-wl org-w3m)))
;全局类型属性值自动补全
(setq org-global-properties (quote (("STYLE_ALL" . "habit"))))
;把习惯图的位置放在日程表默认的右边
(setq org-habit-graph-column 50)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;设置Reminder提醒
;;从日历里移除所有提醒并重建今天的提醒项
(defun bh/org-agenda-to-appt ()
  (interactive)
  (setq appt-time-msg-list nil)
  (org-agenda-to-appt))
;;每次日历显示时重建提醒项
(add-hook 'org-finalize-agenda-hook 'bh/org-agenda-to-appt)
;;这个放在.emacs 的最后，使得Emasc 启动时约会设定
(bh/org-agenda-to-appt)
;;激活约会使得我们得到提醒
(appt-activate t)
;;当我们晚上跨天工作时重设约会
(run-at-time "24:01" nil 'bh/org-agenda-to-appt)


(provide 'org-settings)
